using System;
using System.Drawing;
using System.Drawing.Imaging;

namespace CloudShot.Utils
{
	/// <summary>
	/// Provides functions to capture the entire screen, or a particular window, and save it to a file.
	/// </summary>
	public class ScreenCapture
	{
        /// <summary>
        /// Creates an Image object containing a screen shot of the entire desktop
        /// </summary>
        /// <returns></returns>
        public Image CaptureScreen() 
        {
            return CaptureWindow( User32.GetDesktopWindow() );
        }

        /// <summary>
        /// Creates an Image object containing a screen shot of a specific window
        /// </summary>
        /// <param name="handle">The handle to the window. (In windows forms, this is obtained by the Handle property)</param>
        /// <returns></returns>
        public Image CaptureWindow(IntPtr handle)
        {
            // get te hDC of the target window
            IntPtr hdcSrc = User32.GetWindowDC(handle);
            // get the size
            User32.RECT windowRect = new User32.RECT();
            User32.GetWindowRect(handle,ref windowRect);
            int width = windowRect.Right - windowRect.Left;
            int height = windowRect.Bottom - windowRect.Top;
            // create a device context we can copy to
            IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
            // create a bitmap we can copy it to,
            // using GetDeviceCaps to get the width/height
            IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc,width,height); 
            // select the bitmap object
            IntPtr hOld = GDI32.SelectObject(hdcDest,hBitmap);
            // bitblt over
            GDI32.BitBlt(hdcDest,0,0,width,height,hdcSrc,0,0,GDI32.SRCCOPY);
            // restore selection
            GDI32.SelectObject(hdcDest,hOld);
            // clean up 
            GDI32.DeleteDC(hdcDest);
            User32.ReleaseDC(handle,hdcSrc);

            // get a .NET image object for it
            Image img = Image.FromHbitmap(hBitmap);
            // free up the Bitmap object
            GDI32.DeleteObject(hBitmap);

            return img;
        }

				public Image CaptureWindowClientArea(IntPtr handle)
				{
					// get te hDC of the target window
					IntPtr hdcSrc = User32.GetWindowDC(handle);
					// get the size
					User32.RECT windowRect = new User32.RECT();
					User32.GetWindowRect(handle, ref windowRect);
					int width = windowRect.Right - windowRect.Left;
					int height = windowRect.Bottom - windowRect.Top;
					// create a device context we can copy to
					IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
					// create a bitmap we can copy it to,
					// using GetDeviceCaps to get the width/height
					IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc, width, height);
					// select the bitmap object
					IntPtr hOld = GDI32.SelectObject(hdcDest, hBitmap);
					// bitblt over
					User32.PrintWindow(handle, hdcDest, User32.PW_CLIENTONLY);//does the shot of window even if it is covered by another window
					// restore selection
					GDI32.SelectObject(hdcDest, hOld);
					// clean up 
					GDI32.DeleteDC(hdcDest);
					User32.ReleaseDC(handle, hdcSrc);

					// get a .NET image object for it
					Image img = Image.FromHbitmap(hBitmap);
					// free up the Bitmap object
					GDI32.DeleteObject(hBitmap);

					return img;
				}

        public Image CaptureRectangle(Rectangle windowRect)
        {
          if ((windowRect.Height <= 0) || windowRect.Width <= 0)
            return null;//throw new ArgumentException("The Rectangle has no size", "windowRect");

            IntPtr handle = User32.GetDesktopWindow();

            // get te hDC of the target window
            IntPtr hdcSrc = User32.GetWindowDC(handle);
            // get the size
            //User32.RECT windowRect = new User32.RECT();
            //User32.GetWindowRect(handle, ref windowRect);
            //int width = windowRect.Right - windowRect.Left;
            //int height = windowRect.Bottom - windowRect.Top;
            // create a device context we can copy to
            IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
            // create a bitmap we can copy it to,
            // using GetDeviceCaps to get the width/height
            IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc, windowRect.Width, windowRect.Height);
            // select the bitmap object
            IntPtr hOld = GDI32.SelectObject(hdcDest, hBitmap);
            // bitblt over
            GDI32.BitBlt(hdcDest, 0, 0, windowRect.Width, windowRect.Height,
                hdcSrc, windowRect.Left, windowRect.Top, GDI32.SRCCOPY);
            // restore selection
            GDI32.SelectObject(hdcDest, hOld);
            // clean up 
            GDI32.DeleteDC(hdcDest);
            User32.ReleaseDC(handle, hdcSrc);

            // get a .NET image object for it
            Image img = Image.FromHbitmap(hBitmap);
            // free up the Bitmap object
            GDI32.DeleteObject(hBitmap);

            return img;
        }

        /// <summary>
        /// Captures a screen shot of a specific window, and saves it to a file
        /// </summary>
        /// <param name="handle"></param>
        /// <param name="filename"></param>
        /// <param name="format"></param>
        public void CaptureWindowToFile(IntPtr handle, string filename, ImageFormat format) 
        {
            Image img = CaptureWindow(handle);
            img.Save(filename,format);
        }

        /// <summary>
        /// Captures a screen shot of the entire desktop, and saves it to a file
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="format"></param>
        public void CaptureScreenToFile(string filename, ImageFormat format) 
        {
            Image img = CaptureScreen();
            img.Save(filename,format);
        }

        public void CaptureRectangleToFile(Rectangle rect, string filename, ImageFormat format)
        {
            Image img = CaptureRectangle(rect);
            img.Save(filename, format);
        }
	}
}
